<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

/**
 * 合同调整模型
 * 管理合同的级别调整和其他变更记录
 */
class ContractAdjustment extends Model
{
    use HasFactory;

    /**
     * 表名
     */
    protected $table = 'contract_adjustments';

    /**
     * 可填充字段
     */
    protected $fillable = [
        'contract_id',
        'employee_id',
        'contract_number',
        'adjustment_type',
        'adjustment_category',
        'adjustment_reason',
        'effective_date',
        'adjustment_date',
        'previous_salary',
        'new_salary',
        'salary_adjustment_amount',
        'salary_adjustment_percentage',
        'previous_position',
        'new_position',
        'previous_department',
        'new_department',
        'previous_level',
        'new_level',
        'level_change_reason',
        'benefits_changes',
        'responsibilities_changes',
        'working_condition_changes',
        'other_changes',
        'adjustment_notes',
        'manager_comments',
        'hr_comments',
        'employee_comments',
        'proposed_by',
        'proposed_at',
        'approved_by',
        'approved_at',
        'approval_notes',
        'status',
        'rejection_reason',
        'attachments',
        'supporting_documents',
        'custom_fields',
        'internal_notes',
        'version',
        'is_latest',
    ];

    /**
     * 字段类型转换
     */
    protected $casts = [
        'effective_date' => 'date',
        'adjustment_date' => 'date',
        'proposed_at' => 'date',
        'approved_at' => 'date',
        'previous_salary' => 'decimal:2',
        'new_salary' => 'decimal:2',
        'salary_adjustment_amount' => 'decimal:2',
        'salary_adjustment_percentage' => 'decimal:2',
        'benefits_changes' => 'array',
        'responsibilities_changes' => 'array',
        'working_condition_changes' => 'array',
        'other_changes' => 'array',
        'attachments' => 'array',
        'supporting_documents' => 'array',
        'custom_fields' => 'array',
        'version' => 'integer',
        'is_latest' => 'boolean',
    ];

    /**
     * 日期字段
     */
    protected $dates = [
        'effective_date',
        'adjustment_date',
        'proposed_at',
        'approved_at',
        'created_at',
        'updated_at',
    ];

    // ============ 常量定义 ============

    public const TYPE_SALARY = 'salary';
    public const TYPE_POSITION = 'position';
    public const TYPE_LEVEL = 'level';
    public const TYPE_BENEFITS = 'benefits';
    public const TYPE_RESPONSIBILITIES = 'responsibilities';
    public const TYPE_WORKING_CONDITIONS = 'working_conditions';

    public const CATEGORY_PROMOTION = 'promotion';
    public const CATEGORY_DEMOTION = 'demotion';
    public const CATEGORY_TRANSFER = 'transfer';
    public const CATEGORY_ADJUSTMENT = 'adjustment';
    public const CATEGORY_CORRECTION = 'correction';

    public const STATUS_DRAFT = 'draft';
    public const STATUS_SUBMITTED = 'submitted';
    public const STATUS_APPROVED = 'approved';
    public const STATUS_REJECTED = 'rejected';
    public const STATUS_EFFECTIVE = 'effective';

    // ============ 关联关系 ============

    /**
     * 关联合同
     */
    public function contract(): BelongsTo
    {
        return $this->belongsTo(Contract::class);
    }

    /**
     * 关联员工
     */
    public function employee(): BelongsTo
    {
        return $this->belongsTo(Employee::class);
    }

    // ============ 访问器 ============

    /**
     * 获取调整类型标签
     */
    public function getAdjustmentTypeLabelAttribute(): string
    {
        return match($this->adjustment_type) {
            self::TYPE_SALARY => '薪资调整',
            self::TYPE_POSITION => '岗位调整',
            self::TYPE_LEVEL => '级别调整',
            self::TYPE_BENEFITS => '福利调整',
            self::TYPE_RESPONSIBILITIES => '职责调整',
            self::TYPE_WORKING_CONDITIONS => '工作条件调整',
            default => $this->adjustment_type ?? '未知'
        };
    }

    /**
     * 获取调整类别标签
     */
    public function getAdjustmentCategoryLabelAttribute(): string
    {
        return match($this->adjustment_category) {
            self::CATEGORY_PROMOTION => '晋升',
            self::CATEGORY_DEMOTION => '降职',
            self::CATEGORY_TRANSFER => '调动',
            self::CATEGORY_ADJUSTMENT => '调整',
            self::CATEGORY_CORRECTION => '更正',
            default => $this->adjustment_category ?? '未知'
        };
    }

    /**
     * 获取状态标签
     */
    public function getStatusLabelAttribute(): string
    {
        return match($this->status) {
            self::STATUS_DRAFT => '草稿',
            self::STATUS_SUBMITTED => '已提交',
            self::STATUS_APPROVED => '已批准',
            self::STATUS_REJECTED => '已驳回',
            self::STATUS_EFFECTIVE => '已生效',
            default => $this->status ?? '未知'
        };
    }

    /**
     * 获取薪资调整信息
     */
    public function getSalaryAdjustmentInfoAttribute(): string
    {
        if (!$this->previous_salary || !$this->new_salary) {
            return '无薪资调整';
        }

        $difference = $this->new_salary - $this->previous_salary;
        $percentage = $this->salary_adjustment_percentage;

        if ($difference > 0) {
            return "上调 {$percentage}% (+{$difference})";
        } elseif ($difference < 0) {
            return "下调 {$percentage}% ({$difference})";
        } else {
            return '薪资无变化';
        }
    }

    /**
     * 获取岗位调整信息
     */
    public function getPositionAdjustmentInfoAttribute(): string
    {
        $changes = [];

        if ($this->previous_position !== $this->new_position) {
            $changes[] = "岗位：{$this->previous_position} → {$this->new_position}";
        }

        if ($this->previous_department !== $this->new_department) {
            $changes[] = "部门：{$this->previous_department} → {$this->new_department}";
        }

        return $changes ? implode('；', $changes) : '无岗位调整';
    }

    /**
     * 获取级别调整信息
     */
    public function getLevelAdjustmentInfoAttribute(): string
    {
        if (!$this->previous_level || !$this->new_level) {
            return '无级别调整';
        }

        if ($this->previous_level === $this->new_level) {
            return '级别无变化';
        }

        return "级别：{$this->previous_level} → {$this->new_level}";
    }

    /**
     * 获取是否已生效
     */
    public function getIsEffectiveAttribute(): bool
    {
        return $this->status === self::STATUS_EFFECTIVE
            && $this->effective_date
            && now()->isAfter($this->effective_date);
    }

    /**
     * 获取调整进度
     */
    public function getProgressAttribute(): string
    {
        $steps = [
            'proposed' => $this->proposed_at ? '已提议' : '未提议',
            'approved' => $this->approved_at ? '已批准' : '待批准',
            'effective' => $this->is_effective ? '已生效' : '待生效',
        ];

        $currentStep = '';
        foreach ($steps as $step => $status) {
            if ($status === '已生效') {
                $currentStep = '已完成';
                break;
            } elseif ($status === '待生效') {
                $currentStep = '待生效';
                break;
            } elseif ($status === '待批准') {
                $currentStep = '待批准';
                break;
            }
        }

        return $currentStep ?: '未开始';
    }

    /**
     * 获取是否有富文本备注
     */
    public function getHasRichTextCommentsAttribute(): bool
    {
        return !empty($this->adjustment_notes) ||
               !empty($this->manager_comments) ||
               !empty($this->hr_comments) ||
               !empty($this->employee_comments);
    }

    // ============ 作用域 ============

    /**
     * 最新版本作用域
     */
    public function scopeLatest($query)
    {
        return $query->where('is_latest', true);
    }

    /**
     * 已生效作用域
     */
    public function scopeEffective($query)
    {
        return $query->where('status', self::STATUS_EFFECTIVE)
                    ->where('effective_date', '<=', now());
    }

    /**
     * 按调整类型筛选作用域
     */
    public function scopeByType($query, $type)
    {
        return $query->where('adjustment_type', $type);
    }

    /**
     * 按调整类别筛选作用域
     */
    public function scopeByCategory($query, $category)
    {
        return $query->where('adjustment_category', $category);
    }

    /**
     * 按状态筛选作用域
     */
    public function scopeByStatus($query, $status)
    {
        return $query->where('status', $status);
    }

    /**
     * 薪资调整作用域
     */
    public function scopeSalaryAdjustments($query)
    {
        return $query->where('adjustment_type', self::TYPE_SALARY);
    }

    /**
     * 晋升调整作用域
     */
    public function scopePromotions($query)
    {
        return $query->where('adjustment_category', self::CATEGORY_PROMOTION);
    }

    // ============ 业务方法 ============

    /**
     * 提交调整
     */
    public function submit(string $proposedBy): bool
    {
        $this->status = self::STATUS_SUBMITTED;
        $this->proposed_by = $proposedBy;
        $this->proposed_at = now();

        return $this->save();
    }

    /**
     * 批准调整
     */
    public function approve(string $approvedBy, ?string $notes = null): bool
    {
        $this->status = self::STATUS_APPROVED;
        $this->approved_by = $approvedBy;
        $this->approved_at = now();
        $this->approval_notes = $notes;

        return $this->save();
    }

    /**
     * 驳回调整
     */
    public function reject(string $approvedBy, string $reason): bool
    {
        $this->status = self::STATUS_REJECTED;
        $this->approved_by = $approvedBy;
        $this->approved_at = now();
        $this->rejection_reason = $reason;

        return $this->save();
    }

    /**
     * 生效调整
     */
    public function makeEffective(): bool
    {
        $this->status = self::STATUS_EFFECTIVE;
        $this->adjustment_date = now();

        return $this->save();
    }

    /**
     * 创建新版本
     */
    public function createNewVersion(): self
    {
        // 将当前版本设为非最新
        $this->is_latest = false;
        $this->save();

        // 创建新版本
        $newAdjustment = $this->replicate();
        $newAdjustment->version = $this->version + 1;
        $newAdjustment->is_latest = true;
        $newAdjustment->status = self::STATUS_DRAFT;
        $newAdjustment->save();

        return $newAdjustment;
    }

    /**
     * 添加附件
     */
    public function addAttachment(array $attachment): bool
    {
        $attachments = $this->attachments ?? [];
        $attachments[] = $attachment;

        $this->attachments = $attachments;
        return $this->save();
    }

    /**
     * 添加支撑文件
     */
    public function addSupportingDocument(array $document): bool
    {
        $documents = $this->supporting_documents ?? [];
        $documents[] = $document;

        $this->supporting_documents = $documents;
        return $this->save();
    }

    /**
     * 更新富文本备注
     */
    public function updateRichTextComments(array $comments): bool
    {
        if (isset($comments['adjustment_notes'])) {
            $this->adjustment_notes = $comments['adjustment_notes'];
        }

        if (isset($comments['manager_comments'])) {
            $this->manager_comments = $comments['manager_comments'];
        }

        if (isset($comments['hr_comments'])) {
            $this->hr_comments = $comments['hr_comments'];
        }

        if (isset($comments['employee_comments'])) {
            $this->employee_comments = $comments['employee_comments'];
        }

        return $this->save();
    }

    // ============ 静态方法 ============

    /**
     * 获取调整类型选项
     */
    public static function getAdjustmentTypeOptions(): array
    {
        return [
            self::TYPE_SALARY => '薪资调整',
            self::TYPE_POSITION => '岗位调整',
            self::TYPE_LEVEL => '级别调整',
            self::TYPE_BENEFITS => '福利调整',
            self::TYPE_RESPONSIBILITIES => '职责调整',
            self::TYPE_WORKING_CONDITIONS => '工作条件调整',
        ];
    }

    /**
     * 获取调整类别选项
     */
    public static function getAdjustmentCategoryOptions(): array
    {
        return [
            self::CATEGORY_PROMOTION => '晋升',
            self::CATEGORY_DEMOTION => '降职',
            self::CATEGORY_TRANSFER => '调动',
            self::CATEGORY_ADJUSTMENT => '调整',
            self::CATEGORY_CORRECTION => '更正',
        ];
    }

    /**
     * 获取状态选项
     */
    public static function getStatusOptions(): array
    {
        return [
            self::STATUS_DRAFT => '草稿',
            self::STATUS_SUBMITTED => '已提交',
            self::STATUS_APPROVED => '已批准',
            self::STATUS_REJECTED => '已驳回',
            self::STATUS_EFFECTIVE => '已生效',
        ];
    }

    /**
     * 计算薪资调整
     */
    public static function calculateSalaryAdjustment(
        float $previousSalary,
        float $newSalary
    ): array {
        $amount = $newSalary - $previousSalary;
        $percentage = $previousSalary > 0 ? round(($amount / $previousSalary) * 100, 2) : 0;

        return [
            'amount' => round($amount, 2),
            'percentage' => $percentage,
        ];
    }

    /**
     * 创建级别调整记录
     */
    public static function createLevelAdjustment(
        int $contractId,
        int $employeeId,
        string $previousLevel,
        string $newLevel,
        array $adjustmentData = []
    ): self {
        return self::create(array_merge($adjustmentData, [
            'contract_id' => $contractId,
            'employee_id' => $employeeId,
            'adjustment_type' => self::TYPE_LEVEL,
            'previous_level' => $previousLevel,
            'new_level' => $newLevel,
            'effective_date' => now(),
            'adjustment_reason' => $adjustmentData['reason'] ?? '级别调整',
        ]));
    }

    /**
     * 验证调整数据
     */
    public static function validateAdjustmentData(array $data): array
    {
        $errors = [];

        // 必填字段验证
        $requiredFields = ['contract_id', 'employee_id', 'adjustment_type', 'effective_date'];
        foreach ($requiredFields as $field) {
            if (empty($data[$field])) {
                $errors[] = "{$field} 字段不能为空";
            }
        }

        // 调整类型验证
        $validTypes = array_keys(self::getAdjustmentTypeOptions());
        if (!empty($data['adjustment_type']) && !in_array($data['adjustment_type'], $validTypes)) {
            $errors[] = "无效的调整类型";
        }

        // 调整类别验证
        $validCategories = array_keys(self::getAdjustmentCategoryOptions());
        if (!empty($data['adjustment_category']) && !in_array($data['adjustment_category'], $validCategories)) {
            $errors[] = "无效的调整类别";
        }

        // 状态验证
        $validStatuses = array_keys(self::getStatusOptions());
        if (!empty($data['status']) && !in_array($data['status'], $validStatuses)) {
            $errors[] = "无效的状态";
        }

        // 薪资验证
        if (!empty($data['previous_salary']) && (!is_numeric($data['previous_salary']) || $data['previous_salary'] < 0)) {
            $errors[] = "原薪资必须是有效的非负数";
        }

        if (!empty($data['new_salary']) && (!is_numeric($data['new_salary']) || $data['new_salary'] <= 0)) {
            $errors[] = "新薪资必须是有效的正数";
        }

        if (!empty($data['salary_adjustment_percentage']) && (!is_numeric($data['salary_adjustment_percentage']) || abs($data['salary_adjustment_percentage']) > 200)) {
            $errors[] = "薪资调整百分比必须在-200到200之间";
        }

        return $errors;
    }
}
